/*
 * fetchweath - A beautiful weather forecaster for your terminal.
 * Copyright (C) 2015  BlueGuest, WireFi_hotspot, Unknown Anons
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <math.h>
#include <time.h>
#include <wchar.h>

#define USERAGENT "/tech/ shitposting machine version 13.37"

int units; //Toggle between 0 and 1 for metric or imperial units

typedef struct WeatherInfo
{
  int width;
  int height;
  char icon[4096];
  char country[64];
  char city[64];
  char detailed_condition[64];
  char wind_direction[32];
  time_t day;
  int weather_code;
  float temperature;
  float humidity;
  float pressure;
  float wind;
  struct WeatherInfo *next; /* Head is current weather,
                        the next are following days.
                        List ends with NULL..
                     */
} WeatherInfo;

// Convert code ID to human readable country name.
void get_country_name(const char *code, char *name)
{
  if (!strcmp(code, "AF") ||!strcmp(code, "AFG"))
    sprintf(name, "Afghanistan");
  else if (!strcmp(code, "AL") ||!strcmp(code, "ALB"))
    sprintf(name, "Albania");
  else if (!strcmp(code, "DZ") ||!strcmp(code, "DZA"))
    sprintf(name, "Algeria");
  else if (!strcmp(code, "AS") ||!strcmp(code, "ASM"))
    sprintf(name, "American Samoa");
  else if (!strcmp(code, "AD") ||!strcmp(code, "AND"))
    sprintf(name, "Andorra");
  else if (!strcmp(code, "AO") ||!strcmp(code, "AGO"))
    sprintf(name, "Angola");
  else if (!strcmp(code, "AI") ||!strcmp(code, "AIA"))
    sprintf(name, "Anguilla");
  else if (!strcmp(code, "AQ") ||!strcmp(code, "ATA"))
    sprintf(name, "Antarctica");
  else if (!strcmp(code, "AG") ||!strcmp(code, "ATG"))
    sprintf(name, "Antigua and Barbuda");
  else if (!strcmp(code, "AR") ||!strcmp(code, "ARG"))
    sprintf(name, "Argentina");
  else if (!strcmp(code, "AM") ||!strcmp(code, "ARM"))
    sprintf(name, "Armenia");
  else if (!strcmp(code, "AW") ||!strcmp(code, "ABW"))
    sprintf(name, "Aruba");
  else if (!strcmp(code, "AU") ||!strcmp(code, "AUS"))
    sprintf(name, "Australia");
  else if (!strcmp(code, "AT") ||!strcmp(code, "AUT"))
    sprintf(name, "Austria");
  else if (!strcmp(code, "AZ") ||!strcmp(code, "AZE"))
    sprintf(name, "Azerbaijan");
  else if (!strcmp(code, "BS") ||!strcmp(code, "BHS"))
    sprintf(name, "Bahamas");
  else if (!strcmp(code, "BH") ||!strcmp(code, "BHR"))
    sprintf(name, "Bahrain");
  else if (!strcmp(code, "BD") ||!strcmp(code, "BGD"))
    sprintf(name, "Bangladesh");
  else if (!strcmp(code, "BB") ||!strcmp(code, "BRB"))
    sprintf(name, "Barbados");
  else if (!strcmp(code, "BY") ||!strcmp(code, "BLR"))
    sprintf(name, "Belarus");
  else if (!strcmp(code, "BE") ||!strcmp(code, "BEL"))
    sprintf(name, "Belgium");
  else if (!strcmp(code, "BZ") ||!strcmp(code, "BLZ"))
    sprintf(name, "Belize");
  else if (!strcmp(code, "BJ") ||!strcmp(code, "BEN"))
    sprintf(name, "Benin");
  else if (!strcmp(code, "BM") ||!strcmp(code, "BMU"))
    sprintf(name, "Bermuda");
  else if (!strcmp(code, "BT") ||!strcmp(code, "BTN"))
    sprintf(name, "Bhutan");
  else if (!strcmp(code, "BO") ||!strcmp(code, "BOL"))
    sprintf(name, "Bolivia");
  else if (!strcmp(code, "BA") ||!strcmp(code, "BIH"))
    sprintf(name, "Bosnia");
  else if (!strcmp(code, "BW") ||!strcmp(code, "BWA"))
    sprintf(name, "Botswana");
  else if (!strcmp(code, "BV") ||!strcmp(code, "BVT"))
    sprintf(name, "Bouvet");
  else if (!strcmp(code, "BR") ||!strcmp(code, "BRA"))
    sprintf(name, "Brazil");
  else if (!strcmp(code, "IO") ||!strcmp(code, "IOT"))
    sprintf(name, "British");
  else if (!strcmp(code, "VG") ||!strcmp(code, "VGB"))
    sprintf(name, "British");
  else if (!strcmp(code, "BN") ||!strcmp(code, "BRN"))
    sprintf(name, "Brunei");
  else if (!strcmp(code, "BG") ||!strcmp(code, "BGR"))
    sprintf(name, "Bulgaria");
  else if (!strcmp(code, "BF") ||!strcmp(code, "BFA"))
    sprintf(name, "Burkina");
  else if (!strcmp(code, "BI") ||!strcmp(code, "BDI"))
    sprintf(name, "Burundi");
  else if (!strcmp(code, "KH") ||!strcmp(code, "KHM"))
    sprintf(name, "Cambodia");
  else if (!strcmp(code, "CM") ||!strcmp(code, "CMR"))
    sprintf(name, "Cameroon");
  else if (!strcmp(code, "CA") ||!strcmp(code, "CAN"))
    sprintf(name, "Canada");
  else if (!strcmp(code, "CV") ||!strcmp(code, "CPV"))
    sprintf(name, "Cape Verde");
  else if (!strcmp(code, "KY") ||!strcmp(code, "CYM"))
    sprintf(name, "Cayman Islands");
  else if (!strcmp(code, "CF") ||!strcmp(code, "CAF"))
    sprintf(name, "Central African Republic");
  else if (!strcmp(code, "TD") ||!strcmp(code, "TCD"))
    sprintf(name, "Chad");
  else if (!strcmp(code, "CL") ||!strcmp(code, "CHL"))
    sprintf(name, "Chile");
  else if (!strcmp(code, "CN") ||!strcmp(code, "CHN"))
    sprintf(name, "China");
  else if (!strcmp(code, "CX") ||!strcmp(code, "CXR"))
    sprintf(name, "Christmas Islands");
  else if (!strcmp(code, "CC") ||!strcmp(code, "CCK"))
    sprintf(name, "Cocos");
  else if (!strcmp(code, "CO") ||!strcmp(code, "COL"))
    sprintf(name, "Colombia");
  else if (!strcmp(code, "KM") ||!strcmp(code, "COM"))
    sprintf(name, "Comoros");
  else if (!strcmp(code, "CD") ||!strcmp(code, "COD"))
    sprintf(name, "Congo");
  else if (!strcmp(code, "CG") ||!strcmp(code, "COG"))
    sprintf(name, "Congo");
  else if (!strcmp(code, "CK") ||!strcmp(code, "COK"))
    sprintf(name, "Cook");
  else if (!strcmp(code, "CR") ||!strcmp(code, "CRI"))
    sprintf(name, "Costa");
  else if (!strcmp(code, "CI") ||!strcmp(code, "CIV"))
    sprintf(name, "Cote");
  else if (!strcmp(code, "CU") ||!strcmp(code, "CUB"))
    sprintf(name, "Cuba");
  else if (!strcmp(code, "CY") ||!strcmp(code, "CYP"))
    sprintf(name, "Cyprus");
  else if (!strcmp(code, "CZ") ||!strcmp(code, "CZE"))
    sprintf(name, "Czech");
  else if (!strcmp(code, "DK") ||!strcmp(code, "DNK"))
    sprintf(name, "Denmark");
  else if (!strcmp(code, "DJ") ||!strcmp(code, "DJI"))
    sprintf(name, "Djibouti");
  else if (!strcmp(code, "DM") ||!strcmp(code, "DMA"))
    sprintf(name, "Dominica");
  else if (!strcmp(code, "DO") ||!strcmp(code, "DOM"))
    sprintf(name, "Dominican");
  else if (!strcmp(code, "EC") ||!strcmp(code, "ECU"))
    sprintf(name, "Ecuador");
  else if (!strcmp(code, "EG") ||!strcmp(code, "EGY"))
    sprintf(name, "Egypt");
  else if (!strcmp(code, "SV") ||!strcmp(code, "SLV"))
    sprintf(name, "El Salvador");
  else if (!strcmp(code, "GQ") ||!strcmp(code, "GNQ"))
    sprintf(name, "Equatorial");
  else if (!strcmp(code, "ER") ||!strcmp(code, "ERI"))
    sprintf(name, "Eritrea");
  else if (!strcmp(code, "EE") ||!strcmp(code, "EST"))
    sprintf(name, "Estonia");
  else if (!strcmp(code, "ET") ||!strcmp(code, "ETH"))
    sprintf(name, "Ethiopia");
  else if (!strcmp(code, "FO") ||!strcmp(code, "FRO"))
    sprintf(name, "Faeroe");
  else if (!strcmp(code, "FK") ||!strcmp(code, "FLK"))
    sprintf(name, "Falkland");
  else if (!strcmp(code, "FJ") ||!strcmp(code, "FJI"))
    sprintf(name, "Fiji");
  else if (!strcmp(code, "FI") ||!strcmp(code, "FIN"))
    sprintf(name, "Finland");
  else if (!strcmp(code, "FR") ||!strcmp(code, "FRA"))
    sprintf(name, "France");
  else if (!strcmp(code, "GF") ||!strcmp(code, "GUF"))
    sprintf(name, "French");
  else if (!strcmp(code, "PF") ||!strcmp(code, "PYF"))
    sprintf(name, "French");
  else if (!strcmp(code, "TF") ||!strcmp(code, "ATF"))
    sprintf(name, "French");
  else if (!strcmp(code, "GA") ||!strcmp(code, "GAB"))
    sprintf(name, "Gabon");
  else if (!strcmp(code, "GM") ||!strcmp(code, "GMB"))
    sprintf(name, "Gambia");
  else if (!strcmp(code, "GE") ||!strcmp(code, "GEO"))
    sprintf(name, "Georgia");
  else if (!strcmp(code, "DE") ||!strcmp(code, "DEU"))
    sprintf(name, "Germany");
  else if (!strcmp(code, "GH") ||!strcmp(code, "GHA"))
    sprintf(name, "Ghana");
  else if (!strcmp(code, "GI") ||!strcmp(code, "GIB"))
    sprintf(name, "Gibraltar");
  else if (!strcmp(code, "GR") ||!strcmp(code, "GRC"))
    sprintf(name, "Greece");
  else if (!strcmp(code, "GL") ||!strcmp(code, "GRL"))
    sprintf(name, "Greenland");
  else if (!strcmp(code, "GD") ||!strcmp(code, "GRD"))
    sprintf(name, "Grenada");
  else if (!strcmp(code, "GP") ||!strcmp(code, "GLP"))
    sprintf(name, "Guadaloupe");
  else if (!strcmp(code, "GU") ||!strcmp(code, "GUM"))
    sprintf(name, "Guam");
  else if (!strcmp(code, "GT") ||!strcmp(code, "GTM"))
    sprintf(name, "Guatemala");
  else if (!strcmp(code, "GN") ||!strcmp(code, "GIN"))
    sprintf(name, "Guinea");
  else if (!strcmp(code, "GW") ||!strcmp(code, "GNB"))
    sprintf(name, "Guinea-Bissau");
  else if (!strcmp(code, "GY") ||!strcmp(code, "GUY"))
    sprintf(name, "Guyana");
  else if (!strcmp(code, "HT") ||!strcmp(code, "HTI"))
    sprintf(name, "Haiti");
  else if (!strcmp(code, "HM") ||!strcmp(code, "HMD"))
    sprintf(name, "Heard");
  else if (!strcmp(code, "VA") ||!strcmp(code, "VAT"))
    sprintf(name, "Holy See");
  else if (!strcmp(code, "HN") ||!strcmp(code, "HND"))
    sprintf(name, "Honduras");
  else if (!strcmp(code, "HK") ||!strcmp(code, "HKG"))
    sprintf(name, "Hong Kong");
  else if (!strcmp(code, "HR") ||!strcmp(code, "HRV"))
    sprintf(name, "Hrvatska");
  else if (!strcmp(code, "HU") ||!strcmp(code, "HUN"))
    sprintf(name, "Hungary");
  else if (!strcmp(code, "IS") ||!strcmp(code, "ISL"))
    sprintf(name, "Iceland");
  else if (!strcmp(code, "IN") ||!strcmp(code, "IND"))
    sprintf(name, "India");
  else if (!strcmp(code, "ID") ||!strcmp(code, "IDN"))
    sprintf(name, "Indonesia");
  else if (!strcmp(code, "IR") ||!strcmp(code, "IRN"))
    sprintf(name, "Iran");
  else if (!strcmp(code, "IQ") ||!strcmp(code, "IRQ"))
    sprintf(name, "Iraq");
  else if (!strcmp(code, "IE") ||!strcmp(code, "IRL"))
    sprintf(name, "Ireland");
  else if (!strcmp(code, "IL") ||!strcmp(code, "ISR"))
    sprintf(name, "Israel");
  else if (!strcmp(code, "IT") ||!strcmp(code, "ITA"))
    sprintf(name, "Italy");
  else if (!strcmp(code, "JM") ||!strcmp(code, "JAM"))
    sprintf(name, "Jamaica");
  else if (!strcmp(code, "JP") ||!strcmp(code, "JPN"))
    sprintf(name, "Japan");
  else if (!strcmp(code, "JO") ||!strcmp(code, "JOR"))
    sprintf(name, "Jordan");
  else if (!strcmp(code, "KZ") ||!strcmp(code, "KAZ"))
    sprintf(name, "Kazakhstan");
  else if (!strcmp(code, "KE") ||!strcmp(code, "KEN"))
    sprintf(name, "Kenya");
  else if (!strcmp(code, "KI") ||!strcmp(code, "KIR"))
    sprintf(name, "Kiribati");
  else if (!strcmp(code, "KP") ||!strcmp(code, "PRK"))
    sprintf(name, "Korea");
  else if (!strcmp(code, "KR") ||!strcmp(code, "KOR"))
    sprintf(name, "Korea");
  else if (!strcmp(code, "KW") ||!strcmp(code, "KWT"))
    sprintf(name, "Kuwait");
  else if (!strcmp(code, "KG") ||!strcmp(code, "KGZ"))
    sprintf(name, "Kyrgyz");
  else if (!strcmp(code, "LA") ||!strcmp(code, "LAO"))
    sprintf(name, "Lao");
  else if (!strcmp(code, "LV") ||!strcmp(code, "LVA"))
    sprintf(name, "Latvia");
  else if (!strcmp(code, "LB") ||!strcmp(code, "LBN"))
    sprintf(name, "Lebanon");
  else if (!strcmp(code, "LS") ||!strcmp(code, "LSO"))
    sprintf(name, "Lesotho");
  else if (!strcmp(code, "LR") ||!strcmp(code, "LBR"))
    sprintf(name, "Liberia");
  else if (!strcmp(code, "LY") ||!strcmp(code, "LBY"))
    sprintf(name, "Libyan");
  else if (!strcmp(code, "LI") ||!strcmp(code, "LIE"))
    sprintf(name, "Liechtenstein");
  else if (!strcmp(code, "LT") ||!strcmp(code, "LTU"))
    sprintf(name, "Lithuania");
  else if (!strcmp(code, "LU") ||!strcmp(code, "LUX"))
    sprintf(name, "Luxembourg");
  else if (!strcmp(code, "MO") ||!strcmp(code, "MAC"))
    sprintf(name, "Macao");
  else if (!strcmp(code, "MK") ||!strcmp(code, "MKD"))
    sprintf(name, "Macedonia");
  else if (!strcmp(code, "MG") ||!strcmp(code, "MDG"))
    sprintf(name, "Madagascar");
  else if (!strcmp(code, "MW") ||!strcmp(code, "MWI"))
    sprintf(name, "Malawi");
  else if (!strcmp(code, "MY") ||!strcmp(code, "MYS"))
    sprintf(name, "Malaysia");
  else if (!strcmp(code, "MV") ||!strcmp(code, "MDV"))
    sprintf(name, "Maldives");
  else if (!strcmp(code, "ML") ||!strcmp(code, "MLI"))
    sprintf(name, "Mali");
  else if (!strcmp(code, "MT") ||!strcmp(code, "MLT"))
    sprintf(name, "Malta");
  else if (!strcmp(code, "MH") ||!strcmp(code, "MHL"))
    sprintf(name, "Marshall");
  else if (!strcmp(code, "MQ") ||!strcmp(code, "MTQ"))
    sprintf(name, "Martinique");
  else if (!strcmp(code, "MR") ||!strcmp(code, "MRT"))
    sprintf(name, "Mauritania");
  else if (!strcmp(code, "MU") ||!strcmp(code, "MUS"))
    sprintf(name, "Mauritius");
  else if (!strcmp(code, "YT") ||!strcmp(code, "MYT"))
    sprintf(name, "Mayotte");
  else if (!strcmp(code, "MX") ||!strcmp(code, "MEX"))
    sprintf(name, "Mexico");
  else if (!strcmp(code, "FM") ||!strcmp(code, "FSM"))
    sprintf(name, "Micronesia");
  else if (!strcmp(code, "MD") ||!strcmp(code, "MDA"))
    sprintf(name, "Moldova");
  else if (!strcmp(code, "MC") ||!strcmp(code, "MCO"))
    sprintf(name, "Monaco");
  else if (!strcmp(code, "MN") ||!strcmp(code, "MNG"))
    sprintf(name, "Mongolia");
  else if (!strcmp(code, "MS") ||!strcmp(code, "MSR"))
    sprintf(name, "Montserrat");
  else if (!strcmp(code, "MA") ||!strcmp(code, "MAR"))
    sprintf(name, "Morocco");
  else if (!strcmp(code, "MZ") ||!strcmp(code, "MOZ"))
    sprintf(name, "Mozambique");
  else if (!strcmp(code, "MM") ||!strcmp(code, "MMR"))
    sprintf(name, "Myanmar");
  else if (!strcmp(code, "NA") ||!strcmp(code, "NAM"))
    sprintf(name, "Namibia");
  else if (!strcmp(code, "NR") ||!strcmp(code, "NRU"))
    sprintf(name, "Nauru");
  else if (!strcmp(code, "NP") ||!strcmp(code, "NPL"))
    sprintf(name, "Nepal");
  else if (!strcmp(code, "AN") ||!strcmp(code, "ANT"))
    sprintf(name, "Netherlands");
  else if (!strcmp(code, "NL") ||!strcmp(code, "NLD"))
    sprintf(name, "Netherlands Antilles");
  else if (!strcmp(code, "NC") ||!strcmp(code, "NCL"))
    sprintf(name, "New Caledonia");
  else if (!strcmp(code, "NZ") ||!strcmp(code, "NZL"))
    sprintf(name, "New Zealand");
  else if (!strcmp(code, "NI") ||!strcmp(code, "NIC"))
    sprintf(name, "Nicaragua");
  else if (!strcmp(code, "NE") ||!strcmp(code, "NER"))
    sprintf(name, "Niger");
  else if (!strcmp(code, "NG") ||!strcmp(code, "NGA"))
    sprintf(name, "Nigeria");
  else if (!strcmp(code, "NU") ||!strcmp(code, "NIU"))
    sprintf(name, "Niue");
  else if (!strcmp(code, "NF") ||!strcmp(code, "NFK"))
    sprintf(name, "Norfolk");
  else if (!strcmp(code, "MP") ||!strcmp(code, "MNP"))
    sprintf(name, "Northern");
  else if (!strcmp(code, "NO") ||!strcmp(code, "NOR"))
    sprintf(name, "Norway");
  else if (!strcmp(code, "OM") ||!strcmp(code, "OMN"))
    sprintf(name, "Oman");
  else if (!strcmp(code, "PK") ||!strcmp(code, "PAK"))
    sprintf(name, "Pakistan");
  else if (!strcmp(code, "PW") ||!strcmp(code, "PLW"))
    sprintf(name, "Palau");
  else if (!strcmp(code, "PS") ||!strcmp(code, "PSE"))
    sprintf(name, "Palestine");
  else if (!strcmp(code, "PA") ||!strcmp(code, "PAN"))
    sprintf(name, "Panama");
  else if (!strcmp(code, "PG") ||!strcmp(code, "PNG"))
    sprintf(name, "Papua");
  else if (!strcmp(code, "PY") ||!strcmp(code, "PRY"))
    sprintf(name, "Paraguay");
  else if (!strcmp(code, "PE") ||!strcmp(code, "PER"))
    sprintf(name, "Peru");
  else if (!strcmp(code, "PH") ||!strcmp(code, "PHL"))
    sprintf(name, "Philippines");
  else if (!strcmp(code, "PN") ||!strcmp(code, "PCN"))
    sprintf(name, "Pitcairn");
  else if (!strcmp(code, "PL") ||!strcmp(code, "POL"))
    sprintf(name, "Poland");
  else if (!strcmp(code, "PT") ||!strcmp(code, "PRT"))
    sprintf(name, "Portugal");
  else if (!strcmp(code, "PR") ||!strcmp(code, "PRI"))
    sprintf(name, "Puerto");
  else if (!strcmp(code, "QA") ||!strcmp(code, "QAT"))
    sprintf(name, "Qatar");
  else if (!strcmp(code, "RE") ||!strcmp(code, "REU"))
    sprintf(name, "Reunion");
  else if (!strcmp(code, "RO") ||!strcmp(code, "ROU"))
    sprintf(name, "Romania");
  else if (!strcmp(code, "RU") ||!strcmp(code, "RUS"))
    sprintf(name, "Russian Federation");
  else if (!strcmp(code, "RW") ||!strcmp(code, "RWA"))
    sprintf(name, "Rwanda");
  else if (!strcmp(code, "SH") ||!strcmp(code, "SHN"))
    sprintf(name, "St. Helena");
  else if (!strcmp(code, "KN") ||!strcmp(code, "KNA"))
    sprintf(name, "St. Kitts And Nevis");
  else if (!strcmp(code, "LC") ||!strcmp(code, "LCA"))
    sprintf(name, "St. Lucia");
  else if (!strcmp(code, "PM") ||!strcmp(code, "SPM"))
    sprintf(name, "St. Pierre And Miquelon");
  else if (!strcmp(code, "VC") ||!strcmp(code, "VCT"))
    sprintf(name, "St. Vincent And The Grenadines");
  else if (!strcmp(code, "WS") ||!strcmp(code, "WSM"))
    sprintf(name, "Samoa");
  else if (!strcmp(code, "SM") ||!strcmp(code, "SMR"))
    sprintf(name, "San Marino");
  else if (!strcmp(code, "ST") ||!strcmp(code, "STP"))
    sprintf(name, "Sao Tome And Principe");
  else if (!strcmp(code, "SA") ||!strcmp(code, "SAU"))
    sprintf(name, "Saudi Arabia");
  else if (!strcmp(code, "SN") ||!strcmp(code, "SEN"))
    sprintf(name, "Senegal");
  else if (!strcmp(code, "CS") ||!strcmp(code, "SCG"))
    sprintf(name, "Serbia");
  else if (!strcmp(code, "SC") ||!strcmp(code, "SYC"))
    sprintf(name, "Seychelles");
  else if (!strcmp(code, "SL") ||!strcmp(code, "SLE"))
    sprintf(name, "Sierra");
  else if (!strcmp(code, "SG") ||!strcmp(code, "SGP"))
    sprintf(name, "Singapore");
  else if (!strcmp(code, "SK") ||!strcmp(code, "SVK"))
    sprintf(name, "Slovakia");
  else if (!strcmp(code, "SI") ||!strcmp(code, "SVN"))
    sprintf(name, "Slovenia");
  else if (!strcmp(code, "SB") ||!strcmp(code, "SLB"))
    sprintf(name, "Solomon");
  else if (!strcmp(code, "SO") ||!strcmp(code, "SOM"))
    sprintf(name, "Somalia");
  else if (!strcmp(code, "ZA") ||!strcmp(code, "ZAF"))
    sprintf(name, "South Africa");
  else if (!strcmp(code, "GS") ||!strcmp(code, "SGS"))
    sprintf(name, "South Georgia And The South Sandwich Islands");
  else if (!strcmp(code, "ES") ||!strcmp(code, "ESP"))
    sprintf(name, "Spain");
  else if (!strcmp(code, "LK") ||!strcmp(code, "LKA"))
    sprintf(name, "Sri Lanka");
  else if (!strcmp(code, "SD") ||!strcmp(code, "SDN"))
    sprintf(name, "Sudan");
  else if (!strcmp(code, "SR") ||!strcmp(code, "SUR"))
    sprintf(name, "Suriname");
  else if (!strcmp(code, "SJ") ||!strcmp(code, "SJM"))
    sprintf(name, "Svalbard And Jan Mayen Islands");
  else if (!strcmp(code, "SZ") ||!strcmp(code, "SWZ"))
    sprintf(name, "Swaziland");
  else if (!strcmp(code, "SE") ||!strcmp(code, "SWE"))
    sprintf(name, "Sweden");
  else if (!strcmp(code, "CH") ||!strcmp(code, "CHE"))
    sprintf(name, "Switzerland");
  else if (!strcmp(code, "SY") ||!strcmp(code, "SYR"))
    sprintf(name, "Syrian Arab Republic");
  else if (!strcmp(code, "TW") ||!strcmp(code, "TWN"))
    sprintf(name, "Taiwan");
  else if (!strcmp(code, "TJ") ||!strcmp(code, "TJK"))
    sprintf(name, "Tajikistan");
  else if (!strcmp(code, "TZ") ||!strcmp(code, "TZA"))
    sprintf(name, "Tanzania");
  else if (!strcmp(code, "TH") ||!strcmp(code, "THA"))
    sprintf(name, "Thailand");
  else if (!strcmp(code, "TL") ||!strcmp(code, "TLS"))
    sprintf(name, "Timor-Leste");
  else if (!strcmp(code, "TG") ||!strcmp(code, "TGO"))
    sprintf(name, "Togo");
  else if (!strcmp(code, "TK") ||!strcmp(code, "TKL"))
    sprintf(name, "Tokelau");
  else if (!strcmp(code, "TO") ||!strcmp(code, "TON"))
    sprintf(name, "Tonga");
  else if (!strcmp(code, "TT") ||!strcmp(code, "TTO"))
    sprintf(name, "Trinidad");
  else if (!strcmp(code, "TN") ||!strcmp(code, "TUN"))
    sprintf(name, "Tunisia");
  else if (!strcmp(code, "TR") ||!strcmp(code, "TUR"))
    sprintf(name, "Turkey");
  else if (!strcmp(code, "TM") ||!strcmp(code, "TKM"))
    sprintf(name, "Turkmenistan");
  else if (!strcmp(code, "TC") ||!strcmp(code, "TCA"))
    sprintf(name, "Turks And Caicos Islands");
  else if (!strcmp(code, "TV") ||!strcmp(code, "TUV"))
    sprintf(name, "Tuvalu");
  else if (!strcmp(code, "VI") ||!strcmp(code, "VIR"))
    sprintf(name, "US");
  else if (!strcmp(code, "UG") ||!strcmp(code, "UGA"))
    sprintf(name, "Uganda");
  else if (!strcmp(code, "UA") ||!strcmp(code, "UKR"))
    sprintf(name, "Ukraine");
  else if (!strcmp(code, "AE") ||!strcmp(code, "ARE"))
    sprintf(name, "United Arab Emirate");
  else if (!strcmp(code, "GB") ||!strcmp(code, "GBR"))
    sprintf(name, "United Kingdom");
  else if (!strcmp(code, "UM") ||!strcmp(code, "UMI"))
    sprintf(name, "United States Minor Outlying Islands");
  else if (!strcmp(code, "US") ||!strcmp(code, "USA"))
    sprintf(name, "United States");
  else if (!strcmp(code, "UY") ||!strcmp(code, "URY"))
    sprintf(name, "Uruguay");
  else if (!strcmp(code, "UZ") ||!strcmp(code, "UZB"))
    sprintf(name, "Uzbekistan");
  else if (!strcmp(code, "VU") ||!strcmp(code, "VUT"))
    sprintf(name, "Vanuatu");
  else if (!strcmp(code, "VE") ||!strcmp(code, "VEN"))
    sprintf(name, "Venezuela");
  else if (!strcmp(code, "VN") ||!strcmp(code, "VNM"))
    sprintf(name, "Viet Nam");
  else if (!strcmp(code, "WF") ||!strcmp(code, "WLF"))
    sprintf(name, "Wallis And Futuna Islands");
  else if (!strcmp(code, "EH") ||!strcmp(code, "ESH"))
    sprintf(name, "Western Sahara");
  else if (!strcmp(code, "YE") ||!strcmp(code, "YEM"))
    sprintf(name, "Yemen");
  else if (!strcmp(code, "ZM") ||!strcmp(code, "ZMB"))
    sprintf(name, "Zambia");
  else if (!strcmp(code, "ZW") ||!strcmp(code, "ZWE"))
    sprintf(name, "Zimbabwe");
}

// Fill weather icon according to to the weather code.
void fill_condition_icon(struct WeatherInfo *input)
{
  // Weather symbols comes from here:
  // https://github.com/schachmat/wego/blob/master/we.go

  // Thunderstorm
 if (input->weather_code >= 200 && input->weather_code < 300)
    sprintf(input->icon, 
    "     .-.     "
    "    (   ).   "
    "   (___(__)  "
    "  ‚‘‚‘‚‘‚‘   "
    "  ‚’‚’‚’‚’   ");
// Drizzle 
  else if (input->weather_code >= 300 && input->weather_code < 400)
    sprintf(input->icon, 
    "     .-.     "
    "    (   ).   "
    "   (___(__)  "
    "    . . .   "
    "   .   .    ");
  // 4XX codes are not defined
  else if (input->weather_code >= 400 && input->weather_code < 500)
    sprintf(input->icon, 
    "    .-.      "
    "     __)     "
    "    (        "
    "     `-’     "
    "      •      ");
// Rain
  else if (input->weather_code >= 500 && input->weather_code < 600)
    sprintf(input->icon, 
    " _\\/\"\".-.    "
    "  /\\_(   ).  "
    "  /(___(__)  " 
    "   / / / /   "
    "  / / / /    ");
// Snow
  else if (input->weather_code >= 600 && input->weather_code < 700)
    sprintf(input->icon, 
    " _`/\"\".-.    "
    "  ,\\_(   ).  "
    "   /(___(__) "
    "     *  *  * "
    "    *  *  *  ");
  // Mist/Smoke/Dust/Fog
  else if (input->weather_code >= 700 && input->weather_code < 800)
    sprintf(input->icon, 
    "             "
    " _ - _ - _ - "
    "  _ - _ - _  "
    " _ - _ - _ - "
    "             ");
  // Clear
  else if (input->weather_code == 800)
    sprintf(input->icon, // Hmmm 
    "    \\   /    " // Did u modify something?
    "     .-.     " // No. I simply added it to main.
    " -- (   ) -- " // it segfault with this icon.
    "     `-`     " // ...but why?
    "    /   \\    ");// cuz "icon" was just a pointer not an array. i've fixed that 
  // Ahhh. Sweet. Let's test it.
  // Clouds
  else if (input->weather_code >= 801 && input->weather_code < 900)
    sprintf(input->icon, 
    "             "
    "     .--.    "
    "  .-(    ).  "
    " (___.__)__) "
    "             ");
// Extreme
  else if (input->weather_code >= 900 && input->weather_code < 1000)
    sprintf(input->icon, 
    "  __________ "
    " _\\________/ "
    " \\______/    " 
    "   \\____/    "
    "     \\_/     ");
/* Default case */
else
sprintf(input->icon,
"    .-.      "
"     __)     "
"    (        "
"     `-’     "
"      •      ");
}

/* 
  Drawing functions 
  =================
*/
typedef struct DrawBoard
{
  int width;
  int height;
  char *text;
}DrawBoard;

void *drw_create_board(int width, int height, int bg)
{
  DrawBoard *board = calloc(1, sizeof(DrawBoard));
  board->width = width;
  board->height = height;
  board->text = malloc(width*height);
  memset(board->text, bg, width*height);
  return board;
}

void drw_destroy_board(void *board)
{
  DrawBoard *_board = board;
  free(_board->text);
  free(board);
}

void drw_put_pixel(void *board, int x, int y , char c)
{
  DrawBoard *_board = board;

  if (x < 0 || x >= _board->width ||
     y < 0 || y >=_board->height)
    return;

  _board->text[x + y * _board->width] = c;
}

char drw_get_pixel(void *board, int x, int y)
{
  DrawBoard *_board = board;
  return _board->text[x + y * _board->width];
}

void drw_fill_board(void *board, char c)
{
  DrawBoard *_board = board;
  int y, x;
  
  for (y=0; y < _board->height;y++)
  {
    char *line = _board->text + y * _board->width;
    for (x=0; x < _board->width;x++)
    {
      line[x] = c;
    }
  }
}

void drw_text(void *board, int x, int y, const char *text)
{
  int i;
  
  for (i =0;i < strlen(text);i++)
    drw_put_pixel(board, x+i, y , text[i]);
}

void drw_circle(void *board, int xc, int yc, int a, int b, char c)
{
    int a2 = a * a;
    int b2 = b * b;
    int fa2 = 4 * a2, fb2 = 4 * b2;
    int x, y, sigma;

    /* first half */
    for (x = 0, y = b, sigma = 2*b2+a2*(1-2*b); b2*x <= a2*y; x++)
    {

       drw_put_pixel(board, xc + x, yc + y, c);
       drw_put_pixel(board, xc - x, yc + y, c);
       drw_put_pixel(board, xc + x, yc - y, c);
       drw_put_pixel(board, xc - x, yc - y, c);
        if (sigma >= 0)
        {
            sigma += fa2 * (1 - y);
            y--;
        }
        sigma += b2 * ((4 * x) + 6);
    }

    /* second half */
    for (x = a, y = 0, sigma = 2*a2+b2*(1-2*a); a2*y <= b2*x; y++)
    {
        drw_put_pixel(board, xc + x, yc + y, c);
        drw_put_pixel(board, xc - x, yc + y, c);
        drw_put_pixel(board, xc + x, yc - y, c);
        drw_put_pixel(board, xc - x, yc - y, c);
        if (sigma >= 0)
        {
            sigma += fb2 * (1 - x);
            x--;
        }
        sigma += a2 * ((4 * y) + 6);
    }
}

void drw_line(void *board, int x0, int y0, int x1, int y1, char c)
{
  int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
  int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
  int err = (dx>dy ? dx : -dy)/2, e2;

  for(;;){
    drw_put_pixel(board, x0,y0, c);
    if (x0==x1 && y0==y1) break;
    e2 = err;
    if (e2 >-dx) { err -= dy; x0 += sx; }
    if (e2 < dy) { err += dx; y0 += sy; }
  }
}

void drw_rectangle(void *board, int x, int y, int width, int height, char c)
{
  int i;
  
  for (i=0; i < width;i++)
  {
        drw_put_pixel(board, i + x, y, c);
        drw_put_pixel(board, i + x, y + height - 1, c);
  }
  for (i=0; i < height;i++)
  {
        drw_put_pixel(board, x, i + y, c);
        drw_put_pixel(board, x + width - 1, i + y, c);
  }
}

void drw_sprite(void *board, int xl, int yt, int width, int height, const char *sprite)
{
  int y, x;
  
  for (y=0; y < height; y++) {
    const char *line = sprite + y * width;
    for (x=0; x < width;x++)
        drw_put_pixel(board, x + xl, y + yt, line[x]);
  }
}

void drw_print_board(void *board)
{
  DrawBoard *_board = board;
  int y, x;
  
  for (y=0; y < _board->height;y++)
  {
    char *line = _board->text + y * _board->width;
    for (x=0; x < _board->width;x++)
    {
      printf("%c", line[x]);
    }

    printf("\n");
  }
}

void show_weather(WeatherInfo *info, int width, int height)
{
  void *board = drw_create_board(width, height, ' ');

  int x = (width - info->width) / 3;
  int y = (height - info->height) / 5;

  int k = 0.5 * height;

  drw_rectangle(board, 0, 0, width, height, '#');

  drw_line(board, 0, k, width, k, '#');

  drw_line(board, 0.25 * width, k, 0.25 * width, height, '#');
  drw_line(board, 0.5 * width, k, 0.5 * width, height, '#');
  drw_line(board, 0.75 * width, k, 0.75 * width, height, '#');

  // Show current weather info.
  drw_sprite(board, x, y, info->width, info->height, info->icon);

  drw_text(board, x+info->width, y-2, "Today");
  
  char condition[4096];
  sprintf(condition, "Condition: %s", info->detailed_condition);
  drw_text(board, x+info->width, y, condition);
  
  char country[4096];
  sprintf(country, "Country: %s", info->country);
  drw_text(board, x+info->width, y + 1, country);

  char city[4096];
  sprintf(city, "City: %s", info->city);
  drw_text(board, x+info->width, y + 2, city);

  char temperature[4096];
  if (units == 1)
  sprintf(temperature, "Temperature: %0.1f F", (info->temperature*(9.0/5)+32));
  else
  sprintf(temperature, "Temperature: %0.1f C", info->temperature);
  drw_text(board, x+info->width, y + 3, temperature);

  char humidity[4096];
  sprintf(humidity, "Humidity: %0.1f%c", info->humidity, '%');
  drw_text(board, x+info->width, y + 4, humidity);

  char pressure[4096];
  if (units == 1)
  sprintf(pressure, "Pressure: %0.1f psi", (info->pressure/68.94));
  else
  sprintf(pressure, "Pressure: %0.1f hPa", info->pressure);
  drw_text(board, x+info->width, y + 5, pressure);

  char wind[4096];
  if (units == 1)
  sprintf(wind, "Wind: %0.1f mph %s", (info->wind*2.25), info->wind_direction);
  else
  sprintf(wind, "Wind: %0.1f m/s %s", info->wind, info->wind_direction); 
   drw_text(board, x+info->width, y + 6, wind);

  //  Show weather for next days.
  WeatherInfo *nextDay=info->next;
  float pos=0;
  while(nextDay)
  {
    // print weather for next days here
   drw_sprite(board, (0.05+pos) * width, 0.65 * height, nextDay->width, nextDay->height, nextDay->icon);

    // print day of week for next days
  struct tm *day_tm = gmtime(&nextDay->day);
  char day_of_week[4096];
  strftime (day_of_week, 4096, "%A",day_tm);
  drw_text(board, (0.085+pos)*width, 0.57 * height, day_of_week);

  char temperature[4096];
  if (units == 1)
  sprintf(temperature, "%0.1f F", (nextDay->temperature*(9.0/5)+32));
  else
  sprintf(temperature, "%0.1f C", nextDay->temperature);
  drw_text(board, (0.1+pos)*width, 0.9 * height, temperature);

    pos+=0.25;
    nextDay=nextDay->next;
  }

  drw_print_board(board);
  drw_destroy_board(board);
}

// Key tags for seaching int the JSON request.
#define NFORECASTS       5
#define CITY_START       "name\":\""
#define CITY_END         "\",\"coord"
#define COUNTRY_START    "country\":\""
#define COUNTRY_END      "\",\"population"
#define DT_START         "{\"dt\":"
#define DT_END           ",\"temp"
#define TEMP_START       "\"temp\":{\"day\":"
#define TEMP_END         ",\"min\""
#define PRESSURE_START   "\"pressure\":"
#define PRESSURE_END     ",\"humidity"
#define HUMIDITY_START   "humidity\":"
#define HUMIDITY_END     ",\"weather"
#define WIND_START       ",\"speed\":"
#define WIND_END         ",\"deg"
#define WINDDIR_START    ",\"deg\":"
#define WINDDIR_END      ",\"clouds"
#define CODE_START       "[{\"id\":"
#define CODE_END         ",\"main\":"
#define CONDITION_START  "description\":\""
#define CONDITION_END    "\",\"icon"

/* 
 * getWeather - Download weather data for a given city and load it into a WeatherInfo struct. 
 * Returns 0 on success.
*/
int getWeather(char *city, struct WeatherInfo *input)
{
  int buffer_size = 16000;
  char buffer[buffer_size];
  char resource[128];
  char *url = "api.openweathermap.org";
  char *port = "80"; 
 struct addrinfo hints, *res;
  int sockfd;
  int bytes;
  int degrees;
 
  sprintf(resource, "data/2.5/forecast/daily?q=%s&appid=2de143494c0b295cca9337e1e96b00e0", city);

  memset(&hints, 0, sizeof(hints));
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_family = AF_INET;

  if(getaddrinfo(url, port, &hints, &res) != 0)
    return 1;
  sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
  if (sockfd == -1)
    return 1;
  if(connect(sockfd, res->ai_addr, res->ai_addrlen) != 0)
  return 1;

  sprintf(buffer, "GET /%s HTTP/1.1\nHost: %s\nUser-Agent: %s\nConnection: close\n\n", resource, url, USERAGENT);
  bytes = send(sockfd, buffer, buffer_size, 0);
  
  if (bytes < 1)
  return 1;

  memset(buffer, 0,buffer_size);
  char tmp_buffer[2048];
  int recv_bytes=0;
  for(;;)
  {
    int r = recv(sockfd, tmp_buffer, 2048, 0);
      if(r<1)
        break;
    memcpy (buffer+recv_bytes, tmp_buffer, r);
    recv_bytes+=r;
  }

close(sockfd);

  if (strstr(buffer, "200 OK") == NULL)
    return 1;
  char data[1024];
  char *cur_pos = buffer;
  WeatherInfo *cur_forecast = input;
  int i;
  memset(input,0,sizeof(WeatherInfo));

  memset(data, 0, 1024);
  char *start = strstr(cur_pos, CITY_START);
  char *end = strstr(start, CITY_END);
  start+=strlen(CITY_START); 
  strncpy(data, start, end - start);
  cur_pos=end;
  strcpy(input->city, data);

  memset(data, 0, 1024);
  start = strstr(cur_pos, COUNTRY_START);
  end = strstr(start, COUNTRY_END);
  start+=strlen(COUNTRY_START); 
  strncpy(data, start, end - start);
  cur_pos=end;
  get_country_name(data, cur_forecast->country);

  for (i = 0; i < NFORECASTS; i++) {
    // Get date time.  
    memset(data, 0, 1024);
    start = strstr(cur_pos, DT_START);
    end = strstr(start, DT_END);
    start+=strlen(DT_START); 
    strncpy(data, start, end - start);
    cur_pos=end;
    cur_forecast->day =(time_t)atoi(data);   

    /* Temperature */
    memset(data, 0, 1024);
    start = strstr(cur_pos, TEMP_START);
    end = strstr(start, TEMP_END);
    start+=strlen(TEMP_START); 
    strncpy(data, start, end - start);
    cur_pos=end;
    cur_forecast->temperature = atof(data)-273.15;   

    /* Pressure */
    memset(data, 0, 1024);
    start = strstr(cur_pos, PRESSURE_START);
    end = strstr(start, PRESSURE_END);
    start+=strlen(PRESSURE_START); 
    strncpy(data, start, end - start);
    cur_pos=end;
    cur_forecast->pressure =atof(data);

    /* Humidity */
    memset(data, 0, 1024);
    start = strstr(cur_pos, HUMIDITY_START);
    end = strstr(start, HUMIDITY_END);
    start+=strlen(HUMIDITY_START); 
    strncpy(data, start, end - start);
    cur_pos=end;
    cur_forecast->humidity = atof(data);
    
    /* Weather code */
    memset(data, 0, 1024);
    start = strstr(cur_pos, CODE_START);
    end = strstr(start, CODE_END);
    start+=strlen(CODE_START);
    strncpy(data, start, end - start);
    cur_pos=end;
    cur_forecast->weather_code = atoi(data);
    
    /* Detailed condition */
    memset(data, 0, 1024);
    start = strstr(cur_pos, CONDITION_START);
    end = strstr(start, CONDITION_END);
    start+=strlen(CONDITION_START);         
    strncpy(data, start, end - start);
    cur_pos=end;
    strcpy(cur_forecast->detailed_condition, data);

    /* Wind speed */
    memset(data, 0, 1024);
    start = strstr(cur_pos, WIND_START);
    end = strstr(start, WIND_END);
    start+=strlen(WIND_START);
    strncpy(data, start, end - start);
    cur_pos=end;
    cur_forecast->wind = atof(data);
    
    /* Wind direction */
    memset(data, 0, 1024);
    start = strstr(cur_pos, WINDDIR_START);
    end = strstr(start, WINDDIR_END);
    start+=strlen(WINDDIR_START);
    strncpy(data, start, end - start);
    cur_pos=end;
    degrees = atoi(data);

  /* Determine wind direction */

    if (degrees >= 348 || degrees <= 11)
      sprintf(cur_forecast->wind_direction, "North");
    if (degrees >= 12 && degrees <= 33)
      sprintf(cur_forecast->wind_direction, "North-northeast");
    if (degrees >= 34 && degrees <= 56)
      sprintf(cur_forecast->wind_direction, "Northeast");
    if (degrees >= 57 && degrees <= 78)
      sprintf(cur_forecast->wind_direction, "East-northeast");        
    if (degrees >= 79 && degrees <= 101)
      sprintf(cur_forecast->wind_direction, "East");
    if (degrees >= 102 && degrees <= 123)
      sprintf(cur_forecast->wind_direction, "East-southeast");
    if (degrees >= 124 && degrees <= 146)
      sprintf(cur_forecast->wind_direction, "Southeast");
    if (degrees >= 147 && degrees <= 168)
      sprintf(cur_forecast->wind_direction, "South-southeast");
    if (degrees >= 169 && degrees <= 191)
      sprintf(cur_forecast->wind_direction, "South");
    if (degrees >= 192 && degrees <= 213)
      sprintf(cur_forecast->wind_direction, "South-southwest");
    if (degrees >= 214 && degrees <= 236)
      sprintf(cur_forecast->wind_direction, "Southwest");
    if (degrees >= 237 && degrees <= 258)
      sprintf(cur_forecast->wind_direction, "West-southwest");
    if (degrees >= 259 && degrees <= 281)
      sprintf(cur_forecast->wind_direction, "West");
    if (degrees >= 282 && degrees <= 303)
      sprintf(cur_forecast->wind_direction, "West-northwest");
    if (degrees >= 304 && degrees <= 326)
      sprintf(cur_forecast->wind_direction, "Northwest");
    if (degrees >= 327 && degrees <= 347)
      sprintf(cur_forecast->wind_direction, "North-northwest");

    cur_forecast->width = 13;
    cur_forecast->height = 5;
    fill_condition_icon(cur_forecast);

   if(i<NFORECASTS-1)
    {   
   cur_forecast->next = calloc(1, sizeof(WeatherInfo));
   cur_forecast = cur_forecast->next;
    }
 }
  return 0;
}

void freeWeather(struct WeatherInfo *input)
{
  input = input->next;
 while(input)
 {
   WeatherInfo *next = input->next;
   free(input);
   input = next;
 }
}

int main(int argc, char *argv[])
{
  if (argc != 3) {
    fprintf(stderr, "Usage: %s <city name> <units>\n\n", argv[0]);
    fprintf(stderr, "Units: \n");
    fprintf(stderr, "\t-f : fahrenheit\n");
    fprintf(stderr, "\t-c : celcius\n\n");
    return 1;
  }

  units = 0;
  
  if (strcmp(argv[2], "-c") == 0)
    units = 0;
  if (strcmp(argv[2], "-f") == 0)
    units = 1;
      
  WeatherInfo info;
  if(getWeather(argv[1], &info) != 0) {
    perror("");
    return 1;  
  }

  show_weather(&info, 80, 25);
  freeWeather(&info);
  return 0;
}
